<?php

namespace App\Models\Trip\TripOrderRefund;

use App\Models\Passengers\Repositories\Interfaces\OrderPassengerInterface;
use App\Models\Plane\PlaneOrderPassengers\Repositories\Interfaces\PlaneOrderPassengerRepositoryInterface;
use App\Models\Train\TrainOrderPassengers\Repositories\Interfaces\TrainOrderPassengersRepositoryInterface;
use App\Models\Train\TrainOrderPassengers\TrainOrderPassenger;
use App\Trip\Orders\TripType;
use Eloquent;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;


/**
 * 有票乘客退款记录
 *
 * @property int                       $id
 * @property string                    $user_id      用户id
 * @property string                    $refund_sn    退款单号
 * @property string                    $order_sn     订单单号
 * @property int                       $type         退款项目类型 如:车票,保险费,购票手续费,坐席,票价差
 * @property string                    $name         费用名称
 * @property string                    $passenger_id 如果存在乘客id 表示按乘客id 退款
 * @property int                       $sequence     乘客序号
 * @property string                    $amount       金额
 * @property Carbon|null               $created_at
 * @property Carbon|null               $updated_at
 * @property-read TripOrderRefund|null $refund
 * @method static Builder|TripOrderPassengerRefundDetail newModelQuery()
 * @method static Builder|TripOrderPassengerRefundDetail newQuery()
 * @method static Builder|TripOrderPassengerRefundDetail query()
 * @method static Builder|TripOrderPassengerRefundDetail whereAmount($value)
 * @method static Builder|TripOrderPassengerRefundDetail whereCreatedAt($value)
 * @method static Builder|TripOrderPassengerRefundDetail whereId($value)
 * @method static Builder|TripOrderPassengerRefundDetail whereName($value)
 * @method static Builder|TripOrderPassengerRefundDetail whereOrderSn($value)
 * @method static Builder|TripOrderPassengerRefundDetail wherePassengerId($value)
 * @method static Builder|TripOrderPassengerRefundDetail whereRefundSn($value)
 * @method static Builder|TripOrderPassengerRefundDetail whereSequence($value)
 * @method static Builder|TripOrderPassengerRefundDetail whereType($value)
 * @method static Builder|TripOrderPassengerRefundDetail whereUpdatedAt($value)
 * @method static Builder|TripOrderPassengerRefundDetail whereUserId($value)
 * @property string $out_trade_no 关联的支付单号
 * @method static Builder|TripOrderPassengerRefundDetail whereOutTradeNo($value)
 * @property int|null $trip_type 出行类型 1 火车 2 飞机 3 酒店
 * @method static Builder|TripOrderPassengerRefundDetail whereTripType($value)
 * @mixin Eloquent
 */
class TripOrderPassengerRefundDetail extends RefundDetail
{
    protected $table = "trip_order_passenger_refund_details";
    protected $fillable
                     = [
            "user_id",
            "refund_sn",
            "order_sn",
            "out_trade_no",
            "name",
            "trip_type",        // 出行类型
            "passenger_id",
            "sequence",
            "amount",
        ];


    /**
     * @throws Exception
     */
    public function addMore(TripOrderRefund $refund, array $data): bool
    {

        $validator = Validator::make($data, [
            "*.user_id"      => "required",
            "*.passenger_id" => "required",
            "*.sequence"     => "required",
            "*.refund_sn"    => "required",
            "*.out_trade_no" => "required",
            "*.order_sn"     => "required",
            "*.type"         => "required",
            "*.name"         => "required",
            "*.amount"       => "required",
        ]);

        if ($validator->fails()) {
            throw new Exception("退款参数error".$validator->errors()->first());
        }
        if ($refund->getTripType() == TripType::TRIP_TYPE_TRAIN) {
            $passengerRepo = app(TrainOrderPassengersRepositoryInterface::class);
        } elseif ($refund->getTripType() == TripType::TRIP_TYPE_PLANE) {
            $passengerRepo = app(PlaneOrderPassengerRepositoryInterface::class);
        } else {
            throw new Exception("不支持的出行类型");
        }
        foreach ($data as $key => $detail) {
            $order_passengers = $passengerRepo->findOneOrderPassenger(
                $detail['order_sn'],
                $detail['passenger_id'],
                $detail['sequence']
            );
            if ($this->getPassengerAndRefundTypeDetails($order_passengers, $detail['type'], $detail['out_trade_no'])) {
                Log::error("addMore-退款记录已存在:订单号{$detail['order_sn']},类型{$detail['type']},支付单号{$detail['out_trade_no']}");
                throw new Exception("退款记录已存在");
            }
            $data[$key]['created_at'] = $refund->getCreatedAt();
            $data[$key]['updated_at'] = $refund->getCreatedAt();
        }

        return $this->insert($data);
    }

    /**
     * 获取乘客的票价差价退款记录
     * @param OrderPassengerInterface $passenger
     * @param int                     $type 退款类型
     * @param string                  $out_trade_no 支付单号
     * @return $this|null
     */
    public function getPassengerAndRefundTypeDetails(OrderPassengerInterface $passenger, int $type, string $out_trade_no): ?self
    {
        return $this
            ->where("order_sn", $passenger->getOrderSn())
            ->where("passenger_id", $passenger->getPassengerId())
            ->where("sequence", $passenger->getSequence())
            ->where("type", $type)
            ->where("out_trade_no", $out_trade_no)
            ->first();
    }

    /**
     * @param OrderPassengerInterface $passenger
     * @return Collection
     */
    public function getPassengerRefunds(OrderPassengerInterface $passenger): Collection
    {
        return $this
            ->where("order_sn", $passenger->getOrderSn())
            ->where("passenger_id", $passenger->getPassengerId())
            ->where("sequence", $passenger->getSequence())
            ->get();
    }

    /**
     * 乘客优选 坐席 退款记录
     *
     * @param TrainOrderPassenger $passenger
     * @param string              $out_trade_no 支付单号
     * @return TripOrderPassengerRefundDetail|null
     */
    public function getPassengerSelectSeatRefund(TrainOrderPassenger $passenger, string $out_trade_no): ?self
    {
        return $this->getPassengerAndRefundTypeDetails($passenger, self::SELECTED_SEATS_REFUND, $out_trade_no);
    }

    /**
     * 乘客票价差额 退款记录
     *
     * @param OrderPassengerInterface $passenger
     * @param string                  $out_trade_no 支付单号
     * @return TripOrderPassengerRefundDetail|null
     */
    public function getPassengerTicketPriceDiffRefund(OrderPassengerInterface $passenger, string $out_trade_no): ?self
    {
        return $this->getPassengerAndRefundTypeDetails($passenger, self::TICKET_PRICE_DIFF_FEE_REFUND, $out_trade_no);
    }


    public function addOne(TripOrderRefund $refund, array $data)
    {
        // TODO: Implement addOne() method.
    }
}